package com.wq.feign.provider.filter;

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;

/**
 * @Author:     liuliya
 * @CreateDate:   2020/4/28 23:30
 */
@Slf4j
@Configuration
public class LoggingFilter extends OncePerRequestFilter {

    private static final String REQUEST_PREFIX_NAME = "Request请求: ";
    private static final String RESPONSE_PREFIX_NAME = "Response请求: ";

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        request = new RequestWrapper(request);
        response = new ResponseWrapper(response);
        printRequestLog(request);
        Long startTime = System.currentTimeMillis();
        //Spring通过DispatchServlet处理请求
        filterChain.doFilter(request, response);
        Long endTime = System.currentTimeMillis();
        printResponseLog((ResponseWrapper) response, endTime-startTime);
    }

    private void printRequestLog(final HttpServletRequest request) {
        StringBuilder msg = new StringBuilder();
        msg.append(REQUEST_PREFIX_NAME);
        HttpSession session = request.getSession(false);
        if (session != null) {
            msg.append("sessionId = ").append(session.getId()).append("; ");
        }
        if (request.getMethod() != null) {
            msg.append("method = ").append(request.getMethod()).append("; ");
        }
        if (request.getContentType() != null) {
            msg.append("contentType = ").append(request.getContentType()).append("; ");
        }
        msg.append("uri = ").append(request.getRequestURI());
        if (request.getQueryString() != null) {
            msg.append('?').append(request.getQueryString());
        }

        if (request instanceof RequestWrapper && !isMultipart(request) && !isBinaryContent(request)) {
            RequestWrapper requestWrapper = (RequestWrapper) request;
            msg.append("; payload = ").append(requestWrapper.getRequestBodyString(request));
        }
        log.info(msg.toString());
    }

    private boolean isBinaryContent(final HttpServletRequest request) {
        if (request.getContentType() == null) {
            return false;
        }
        return request.getContentType().startsWith("image")
                || request.getContentType().startsWith("video")
                || request.getContentType().startsWith("audio");
    }

    private boolean isMultipart(final HttpServletRequest request) {
        return request.getContentType() != null
                && request.getContentType().startsWith("multipart/form-data");
    }

    private void printResponseLog(final ResponseWrapper response, long duration) {
        StringBuilder msg = new StringBuilder();
        msg.append(RESPONSE_PREFIX_NAME);

        msg.append("payload = ").append(new String(response.toByteArray(), Charset.defaultCharset()))
                .append(";用时(ms):").append(duration);

        log.info(msg.toString());
    }
}
